library ieee;
use ieee.std_logic_1164.all;
use IEEE.NUMERIC_STD.all;
use work.typeDefinitions.all;

entity memStage is
  port (
    clk        : in std_logic;
    nReset     : in std_logic;
    holdStage  : in std_logic;
    invalidate : in std_logic;

    nPC_in         : in std_logic_vector(31 downto 0);
    upper_in       : in std_logic_vector(31 downto 0);
    aluResult_in   : in std_logic_vector(31 downto 0);
    busB_in        : in std_logic_vector(31 downto 0);
    destination_in : in std_logic_vector(4 downto 0);
    rt_in          : in std_logic_vector(4 downto 0);
    instruction_in : in operation;

    memWait   : in  std_logic;
    dMemDataR : in  std_logic_vector(31 downto 0);
    dMemDataW : out std_logic_vector(31 downto 0);
    dMemAddr  : out std_logic_vector(31 downto 0);
    dMemWen   : out std_logic;
    dMemRen   : out std_logic;

    forwardIn  : in  memForwardIn;
    forwardOut : out memForwardOut;

    upper       : out std_logic_vector(31 downto 0);
    aluResult   : out std_logic_vector(31 downto 0);
    dataMem     : out std_logic_vector(31 downto 0);
    destination : out std_logic_vector(4 downto 0);
    instruction : out operation;
    nPC         : out std_logic_vector(31 downto 0));
end memStage;

architecture memStage_arch of memStage is

  component memInterstageReg
    port (
      clk        : in std_logic;
      nReset     : in std_logic;
      holdStage  : in std_logic;
      invalidate : in std_logic;

      nPC_in         : in std_logic_vector(31 downto 0);
      upper_in       : in std_logic_vector(31 downto 0);
      aluResult_in   : in std_logic_vector(31 downto 0);
      dataMem_in     : in std_logic_vector(31 downto 0);
      destination_in : in std_logic_vector(4 downto 0);

      instruction_in : in operation;

      upper       : out std_logic_vector(31 downto 0);
      aluResult   : out std_logic_vector(31 downto 0);
      dataMem     : out std_logic_vector(31 downto 0);
      destination : out std_logic_vector(4 downto 0);
      instruction : out operation;
      nPC         : out std_logic_vector(31 downto 0));
  end component;

  signal op : operation;
begin  -- fetchInterstageReg  

  op                     <= instruction_in;
  dMemAddr               <= aluResult_in;  --handle "HALTED" business in arbiter
  forwardOut.aluResult   <= aluResult_in;
  forwardOut.destination <= destination_in;
  forwardOUt.rt          <= rt_in;



  forwB : process (busB_in, forwardIn)
  begin  -- process t_rdat1
    case forwardIn.selB is
      when '1' =>
        dMemDataW <= forwardIn.busB;
      when others =>
        dMemDataW <= busB_in;
    end case;
  end process forwB;

  inter_c : memInterstageReg port map
    (
      clk            => clk,
      nReset         => nReset,
      holdStage      => holdStage,
      invalidate     => invalidate,
      nPC_in         => nPC_in,
      upper_in       => upper_in,
      aluResult_in   => aluResult_in,
      dataMem_in     => dMemDataR,
      destination_in => destination_in,
      instruction_in => instruction_in,
      upper          => upper,
      aluresult      => aluResult,
      dataMem        => dataMem,
      destination    => destination,
      instruction    => instruction,
      nPC            => nPC
      );

  memRead : process(op)
  begin
    case op is
      when o_lw =>
        dMemRen <= '1';
      when others =>
        dMemRen <= '0';
    end case;

  end process memRead;

  memWrite : process (op)
  begin  -- process memW
    case op is
      when o_sw =>                      --not sure if there are more here!!!
        dMemWen <= '1';
      when others =>
        dMemWen <= '0';
    end case;
  end process memWrite;

end memStage_arch;
